#pragma once 

#include <ncurses.h>
#include <pthread.h>
#include <iostream>
#include <vector>

#include "ChatClient.hpp"
#include "Connect.hpp"
using namespace std;

class ChatWindow;
class Pram
{
    public:
        Pram(int num,ChatWindow* cw,ChatClient* cc)
        {
            pthread_num_ = num;
            cc_ = cc;
            cw_ = cw;
        }
    public:
        //线程号
        int pthread_num_;
        ChatClient* cc_;
        ChatWindow* cw_;
};


class ChatWindow
{
    public:
        ChatWindow()
        {
            header_ = NULL;
            output_ = NULL;
            user_list_ = NULL;
            input_ = NULL;
            pthread_mutex_init(&lock_win_,NULL);
            vec_.clear();
        }
        ~ChatWindow()
        {
            if(header_)
            {
                delwin(header_);
            }
            if(output_)
            {
                delwin(output_);
            }
            if(user_list_)
            {
                delwin(user_list_);
            }
            if(input_)
            {
                delwin(input_);
            }
            pthread_mutex_destroy(&lock_win_);
            endwin();
        }
        int Start(ChatClient* uc)
        {
            //初始化界面
            initscr();
            for(int i = 0; i < 4; i++)
            {
                Pram* pram = new Pram(i,this,uc);
                if(!pram)
                {
                    LOG(ERROR,"new Pram faild") << endl;
                    exit(1);
                }
                //创建线程
                pthread_t tid;
                int ret = pthread_create(&tid,NULL,RunWindowStart,(void*)pram);
                if(ret < 0)
                {
                    LOG(ERROR,"pthread_create faild") << endl;
                    return -1;
                }

                vec_.push_back(tid);

            }

            //等待所有线程结束
            for(size_t i = 0; i < vec_.size();i++)
            {
                pthread_join(vec_[i],NULL);
            }
            return 0;
        }

        static void* RunWindowStart(void* arg)
        {
            Pram* pram = (Pram*)arg;
            int pthread_num = pram->pthread_num_;
            ChatClient* cc = pram->cc_;
            ChatWindow* cw = pram->cw_;

            switch(pthread_num)
            {
                case 0:
                    {
                        //header
                        cw->RunHeader();
                        break;
                    }
                case 1:
                    {
                        //output
                        cw->RunOutput(cc);     
                        break;
                    }
                case 2:
                    {
                        //user_list
                        cw->RunOutput(cc);
                        break;
                    }
                case 3:
                    {
                        //intput
                        cw->RunIntput(cc);
                        break;
                    }
            }
        }
        void RunIntput(ChatClient* cc)
        {
            WINDOW* old_input = NULL;
            while(1)
            {
                input_ = newwin(LINES/5,COLS,(LINES*4)/5,0);
                box(input_,0,0);
                if(old_input)
                {
                    delwin(old_input);
                }
                string tips = "please input msg:";
                mvwaddstr(input_,1,1,tips.c_str());
                RefreshWin(input_);

                char buf[UDP_DATA_MAX_LEN] = {0};
                wgetnstr(input_,buf,sizeof(buf)-1);

                UdpMsg um;
                um.name_ = cc->GetMe().name_;
                um.school_ = cc->GetMe().school_;
                um.id_ = cc->GetMe().my_id_;
                um.msg_.assign(buf,strlen(buf));


                string send_msg;
                um.serialize(&send_msg);
                
                cc->SendMsg(send_msg);

                old_input = input_;
                sleep(1);

            }
        }

        void RunUserlist(ChatClient* cc)
        {
            WINDOW* old_user_list_ = NULL;
            int line = 1;
            int cols = 1;
            while(1)
            {
                user_list_ = newwin((3*LINES)/5,COLS/4,LINES/5,(3*COLS)/4);
                box(user_list_,0,0);
                RefreshWin(user_list_);

                if(old_user_list_)
                {
                    delwin(old_user_list_);
                }

                vector<UdpMsg> vec = cc->GetVec();

                for(size_t i = 0; i < vec.size();i++)
                {
                    string msg;
                    msg += vec[i].name_;
                    msg += "-";
                    msg += vec[i].school_;
                    
                    mvwaddstr(user_list_,line+i,cols,msg.c_str());
                    RefreshWin(user_list_);
                }
                old_user_list_ = user_list_;
                sleep(1);
            }
        }

        void RunOutput(ChatClient* cc)
        {
            int line = 1;
            int cols = 1;

            DrowOutput(output_);

            int y,x;
            getmaxyx(output_,y,x);
            string msg;

            while(1)
            {
                msg.clear();
                //调用udp接收
                cc->RecvMsg(&msg);

                //udp的反序列化
                UdpMsg um;
                um.deserialize(msg);

                //组织展示在窗口上
                //name-school:msg 
                string show_msg;
                show_msg += um.name_;
                show_msg += "-";
                show_msg += um.school_;
                show_msg += ":";
                show_msg += um.msg_;
                
                if(line >= y-2)
                {
                    DrowOutput(output_);
                    line = 1;
                }
                
                //把show_msg放到output框中展示
                mvwaddstr(output_,line,cols,show_msg.c_str());
                RefreshWin(output_);

                line++;
                vector<UdpMsg> vec = cc->GetVec();

                int flag = 1;
                //当服务端第一次给客户端推送信息的时候，此时客户端并没有保存在线用户列表，也就是说，vec.size()=0
                
                for(size_t i = 0;i < vec.size();i++)
                {
                    //接收到的udp消息当中的用户id，和客户端保存的在线用户id比较
                    if(um.id_ ==  vec[i].id_)
                    {
                        flag = 0;
                        break;
                    }
                    flag = 1;
                }
                if(flag == 1)
                {
                    cc->GetVec().push_back(um);
                }

            }
        }

        void DrowOutput(WINDOW* win)
        {
            output_ = newwin((LINES*3)/5,(COLS*3)/4,LINES/5,0);
            box(output_,0,0);
            RefreshWin(output_);
        }

        void RefreshWin(WINDOW* win)
        {
            pthread_mutex_lock(&lock_win_);
            wrefresh(win);
            pthread_mutex_unlock(&lock_win_);
        }

        void RunHeader()
        {
            WINDOW* old_header_ = NULL;
            while(1)
            {
                //创建宽为LINES/5,长COLS的框
                header_ = newwin(LINES/5,COLS,0,0);
                if(old_header_)
                {
                    delwin(old_header_);
                }
                //实线画框
                box(header_,0,0);
                RefreshWin(header_);

                string msg = "welcome to our chat system";

                int y,x;
                getmaxyx(header_,y,x);
                mvwaddstr(header_,y/2,(x-msg.size())/2,msg.c_str());
                RefreshWin(header_);
                old_header_ = header_;
                sleep(1);
            }
        }

    private:
        WINDOW* header_;
        WINDOW* output_;
        WINDOW* user_list_;
        WINDOW* input_;
        pthread_mutex_t lock_win_;
        vector<pthread_t> vec_; 

};
